﻿using BrightIdeasSoftware;
using ComponentFactory.Krypton.Toolkit;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TaggingToolkit.Controls
{
    /// <summary>
    /// This renderer highlights substrings that match a given text filter. 
    /// </summary>
    public class TestRenderer : HighlightTextRenderer
    {
        internal const TextFormatFlags NormalTextFormatFlags = TextFormatFlags.NoPrefix |
                                                       TextFormatFlags.EndEllipsis |
                                                       TextFormatFlags.PreserveGraphicsTranslateTransform;
        private IPalette _palette;

        /// <summary>
        /// Create a HighlightTextRenderer
        /// </summary>
        public TestRenderer() : base()
        {
            _palette = KryptonManager.CurrentGlobalPalette;

            if (_palette != null)
                _palette.PalettePaint += new EventHandler<PaletteLayoutEventArgs>(OnPalettePaint);

            KryptonManager.GlobalPaletteChanged += new EventHandler(OnGlobalPaletteChanged);
        }

        private void OnPalettePaint(object sender, PaletteLayoutEventArgs e)
        {
            ListView?.Invalidate();
        }

        private void OnGlobalPaletteChanged(object sender, EventArgs e)
        {
            // (5) Unhook events from old palette
            if (_palette != null)
                _palette.PalettePaint -= new EventHandler<PaletteLayoutEventArgs>(OnPalettePaint);

            // (6) Cache the new IPalette that is the global palette
            _palette = KryptonManager.CurrentGlobalPalette;

            // (7) Hook into events for the new palette
            if (_palette != null)
                _palette.PalettePaint += new EventHandler<PaletteLayoutEventArgs>(OnPalettePaint);

            // (8) Change of palette means we should repaint to show any changes
            ListView?.Invalidate();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // (10) Unhook from the palette events
                if (_palette != null)
                {
                    _palette.PalettePaint -= new EventHandler<PaletteLayoutEventArgs>(OnPalettePaint);
                    _palette = null;
                }

                // (11) Unhook from the static events, otherwise we cannot be garbage collected
                KryptonManager.GlobalPaletteChanged -= new EventHandler(OnGlobalPaletteChanged);
            }

            base.Dispose(disposing);
        }


        /// <summary>
        /// Create a HighlightTextRenderer
        /// </summary>
        /// <param name="filter"></param>
        public TestRenderer(TextMatchFilter filter)
            : this()
        {
            this.Filter = filter;
        }

        /// <summary>
        /// Return the Color that is the background color for this item's cell
        /// </summary>
        /// <returns>The background color of the subitem</returns>
        public override Color GetBackgroundColor()
        {
            if (!this.ListView.Enabled)
                return _palette.GetBackColor1(PaletteBackStyle.ContextMenuInner, PaletteState.Disabled);

            if (this.IsItemSelected && !this.ListView.UseTranslucentSelection && this.ListView.FullRowSelect)
                return this.GetSelectedBackgroundColor();

            if (this.SubItem == null || this.ListItem.UseItemStyleForSubItems)
                return _palette.GetBackColor1(PaletteBackStyle.ContextMenuInner, PaletteState.Normal);

            return _palette.GetBackColor1(PaletteBackStyle.ContextMenuInner, PaletteState.Normal);
        }

        /// <summary>
        /// Return the color of the background color when the item is selected
        /// </summary>
        /// <returns>The background color of the subitem</returns>
        public override Color GetSelectedBackgroundColor()
        {
            if (this.ListView.Focused)
                return _palette.GetBackColor1(PaletteBackStyle.ButtonAlternate, PaletteState.Pressed);

            if (!this.ListView.HideSelection)
                return _palette.GetBackColor1(PaletteBackStyle.ButtonAlternate, PaletteState.Pressed);

            return _palette.GetBackColor1(PaletteBackStyle.ButtonAlternate, PaletteState.Pressed);
        }

        /// <summary>
        /// Return the color to be used for text in this cell
        /// </summary>
        /// <returns>The text color of the subitem</returns>
        public override Color GetForegroundColor()
        {
            if (this.IsItemSelected &&
                !this.ListView.UseTranslucentSelection &&
                ((this.Column != null && this.Column.Index == 0) || this.ListView.FullRowSelect))
                return _palette.GetContentShortTextColor1(PaletteContentStyle.ButtonAlternate, PaletteState.Normal);

            return _palette.GetContentShortTextColor1(PaletteContentStyle.ButtonAlternate, PaletteState.Normal);
        }

        /// <summary>
        /// Return the color of the foreground color when the item is selected
        /// </summary>
        /// <returns>The foreground color of the subitem</returns>
        public override Color GetSelectedForegroundColor()
        {
            if (this.ListView.Focused)
                return _palette.GetContentShortTextColor1(PaletteContentStyle.ButtonAlternate, PaletteState.Pressed);

            if (!this.ListView.HideSelection)
                return _palette.GetContentShortTextColor1(PaletteContentStyle.ButtonAlternate, PaletteState.Pressed);

            return _palette.GetContentShortTextColor1(PaletteContentStyle.ButtonAlternate, PaletteState.Pressed);
        }

        /// <summary>
        /// Print the given text in the given rectangle using only GDI routines
        /// </summary>
        /// <param name="g"></param>
        /// <param name="r"></param>
        /// <param name="txt"></param>
        /// <remarks>
        /// The native list control uses GDI routines to do its drawing, so using them
        /// here makes the owner drawn mode looks more natural.
        /// <para>This method doesn't honour the CanWrap setting on the renderer. All
        /// text is single line</para>
        /// </remarks>
        protected override void DrawTextGdi(Graphics g, Rectangle r, String txt)
        {
            if (this.ShouldDrawHighlighting)
                this.DrawGdiTextHighlighting(g, r, txt);

            Color backColor = Color.Transparent;
            if (this.IsDrawBackground && this.IsItemSelected && (this.Column != null && this.Column.Index == 0) && !this.ListView.FullRowSelect)
                backColor = GetSelectedBackgroundColor();

            TextFormatFlags flags = NormalTextFormatFlags | this.CellVerticalAlignmentAsTextFormatFlag;

            // I think there is a bug in the TextRenderer. Setting or not setting SingleLine doesn't make 
            // any difference -- it is always single line.
            if (!this.CanWrap)
                flags |= TextFormatFlags.SingleLine;
            TextRenderer.DrawText(g, txt, this.Font, r, this.GetForegroundColor(), backColor, flags);
        }

        /// <summary>
        /// Draw the text using GDI+
        /// </summary>
        /// <param name="g"></param>
        /// <param name="r"></param>
        /// <param name="txt"></param>
        //protected override void DrawTextGdiPlus(Graphics g, Rectangle r, string txt)
        //{
        //    base.DrawTextGdiPlus(g, r, txt);
        //}

        protected override void DrawTextGdiPlus(Graphics g, Rectangle r, String txt)
        {
            if (this.ShouldDrawHighlighting)
                this.DrawGdiPlusTextHighlighting(g, r, txt);

            using (StringFormat fmt = this.StringFormatForGdiPlus)
            {
                // Draw the background of the text as selected, if it's the primary column
                // and it's selected and it's not in FullRowSelect mode.
                Font f = this.Font;
                if (this.IsDrawBackground && this.IsItemSelected && (this.Column != null && this.Column.Index == 0) && !this.ListView.FullRowSelect)
                {
                    SizeF size = g.MeasureString(txt, f, r.Width, fmt);
                    Rectangle r2 = r;
                    r2.Width = (int)size.Width + 1;
                    using (Brush brush = new SolidBrush(this.GetSelectedBackgroundColor()))
                    {
                        g.FillRectangle(brush, r2);
                    }
                }
                RectangleF rf = r;

                using (var textBrush = new SolidBrush(_palette.GetContentShortTextColor1(PaletteContentStyle.ButtonAlternate, PaletteState.Normal)))
                {
                    g.DrawString(txt, f, textBrush, rf, fmt);
                }
            }
        }
    }
}
